﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

using Alicanto.Execution;
using Alicanto.Lexing;

namespace Alicanto
{
    public class Template<T>
    {
        delegate void RunTemplate(ExecutionDomain domain);

        private RunTemplate _del;
        private ExecutionDomain _domain;
        private StringBuilder _printOutput;


        public Template(string str)
        {
            TokenSequence tokens = Lexer.Create().Tokenize(str, true);

            _domain = new ExecutionDomain();
            _domain.Print = new Action<object>(value =>
            {
                _printOutput.Append(value);
            });

            ParameterExpression target = Expression.Parameter(typeof(T));
            Parser parser = new Parser(_domain);

            Expression<RunTemplate> lambda = Expression.Lambda<RunTemplate>(
                Expression.Block(
                    parser.Parse(tokens)
                ),
                new ParameterExpression[] { _domain.Self }
            );

            _del = lambda.Compile();
        }

        public string Run(T target)
        {
            _printOutput = new StringBuilder();
            _del(_domain);

            return _printOutput.ToString();
        }
    }
}
